#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <boost/regex.hpp>
#include "Header.h"
#include "../core/_8BitConverter.h"

using namespace kc_sf;

// --------------------------------------------------------- //

Header::Header(
	const std::string &_name,
	const std::string &value )
: h_name (_name)
{
	h_value = UnicodeString();

	// odkodowujemy wartosc naglowka (encoded-words)

	// "=?"charset"?"encoding"?"encoded−text"?="
	boost::regex expression( "=\\?([-!#-'_\\*\\+.0-9^-`a-zA-Z\\{-~\\]]+)\\?(Q|B|q|b)\\?([^? ]+)\\?=" );

	boost::match_results <std::string::const_iterator> what;
	boost::match_flag_type flags = boost::match_default;

	bool no_matches = true;
	std::string::const_iterator
		start = value.begin(),
		match_pos = start,
		end = value.end();
	while( boost::regex_search( start, end, what, expression, flags ) )
	{
		if( no_matches )
			no_matches = false;

		// zwykly tekst
		match_pos = what[0].first;
		if( match_pos > start )
		{
			size_t start_pos = *start, end_pos = *( what[0].first );
			h_value += UnicodeString(
				value.substr( start_pos, end_pos - start_pos ).c_str() );
		}

		// encoded-word
		// what[0] - cale dopasowanie
		// what[1] - charset
		// what[2] - encoding
		// what[3] - encoded-text
		std::string charset( what[1].first, what[1].second );
		std::string encoding_str( what[2].first, what[2].second );
		EncodingType encoding = encoding_str == "q" || encoding_str == "Q" ? Qp : Base64;
		std::string encoded_word( what[3].first, what[3].second );

		UnicodeString ustring;
		_8BitConverter conv( encoding, charset);
		conv.decode( encoded_word, ustring );
		h_value += ustring;

		start = what[0].second;

		flags |= boost::match_prev_avail;
		flags |= boost::match_not_bob;
	}

	if( no_matches )
		h_value = UnicodeString( value.c_str() );

	h_value.trim();
}

// --------------------------------------------------------- //

Header * Header::clone() const
{
	return new Header (*this);
}

// --------------------------------------------------------- //

const std::string & Header::getName() const
{
	return h_name;
}

// --------------------------------------------------------- //

void Header::setName(const std::string & _name)
{
	h_name = _name;
}

// --------------------------------------------------------- //

UnicodeString Header::getValue() const
{
	return h_value;
}

// --------------------------------------------------------- //

void Header::setValue(const std::string & _value)
{
	h_name = _value;
}
